package protocol

import (
	"encoding/binary"
	"gitee.com/crack007/goose"
	"gitee.com/crack007/goose/core/server"
	"gitee.com/crack007/udp-penetrate/src/common/constant"
	"net"
)

// 发起端和目标主动连接
type CtoCHandshakeReqProtocol struct {
	TargetHost string // 目标的公网ip
	TargetPort uint16 // 目标的公网端口
}

func NewCtoCHandshakeReqProtocol() *CtoCHandshakeReqProtocol {
	return &CtoCHandshakeReqProtocol{}
}

func (p *CtoCHandshakeReqProtocol) Code() uint32 {
	return constant.CMD_CTOCHANDSHAKE_REQ
}

// 主动发起的client需要处理
func (p *CtoCHandshakeReqProtocol) Process(session *server.Session, clientConn *net.UDPConn) IProtocol {
	// 使用本地端口和目标建立连接

	go func() {
		for {
			var readErr error
			var buf = make([]byte, 0xffff)
			n, _, readErr := clientConn.ReadFromUDP(buf)
			if readErr != nil {
				goose.GetLogger().Warn("ReadFromUDP err=%s", readErr.Error())
				return
			}
			iProtocol, err := UnpackData(buf[:n])
			if err != nil {
				return
			}
			resp := iProtocol.Process(session, clientConn)
			if resp != nil {
				respData, err := PackData(resp)
				if err != nil {
					return
				}
				clientConn.Write(respData)
			}
		}
	}()
	return nil
}

func (p *CtoCHandshakeReqProtocol) Marshall() []byte {
	var body = make([]byte, 4)
	binary.BigEndian.PutUint16(body, p.TargetPort)
	body = append(body, []byte(p.TargetHost)...)
	return body
}

func (p *CtoCHandshakeReqProtocol) UnMarshall(data []byte) {
	p.TargetPort = binary.BigEndian.Uint16(data[:4])
	p.TargetHost = string(data[4:])
}
